#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <error.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>



#define TASK_NUM 10
typedef void(*task_t)();
task_t tasks[TASK_NUM];

void task1()
{
    printf("这是一个执行打印日志的任务, pid: %d, ppid: %d\n", getpid(), getppid());
}


void task2()
{
    printf("这是一个检测网络环境安全的任务, pid: %d, ppid: %d\n", getpid(), getppid());
}

void task3()
{
    printf("这是一个隐藏任务, pid: %d, ppid: %d\n", getpid(), getppid());
}

// 任务管理
int AddTask(task_t t);
void InitTask()
{
    for(int i = 0; i < TASK_NUM; i++) tasks[i] = NULL;
    AddTask(task1);
    AddTask(task2);
    AddTask(task3);
    
}


int AddTask(task_t t)
{
    int pos = 0;
    for(;pos < TASK_NUM; pos++)
    {
        if(!tasks[pos]) break;
    }
    if(pos == TASK_NUM) return -1;
    tasks[pos] = t;
    return 0;
}


void DelTask();



void ExecuteTask()
{
    for(int i = 0; i < TASK_NUM; i++)
    {
        if(!tasks[i]) continue;

        tasks[i]();
    }
}

int main()
{
    InitTask();
    pid_t id = fork();
    if(id < 0 )
    {
        perror("fork");
        return 1;
    }
    else if(id == 0)
    {
        // 子进程
        int cnt = 5;
        while(cnt--)
        {
            printf("i am child, pid: %d, ppid: %d, cnt, %d\n", getpid(), getppid(), cnt);
            sleep(1);
        }
        exit(11);
    }
    else 
    {
        // 父进程
        // 专门用来等待子进程
        int status = 0;
        // 非阻塞轮询
        while(1)
        {

            pid_t ret = waitpid(id, &status, WNOHANG);
            if(ret > 0)
            {
                if(WIFEXITED(status))
                {
                    printf("进程正常退出, exit code: %d\n", WEXITSTATUS(status));
                }
                else 
                {
                    printf("进程异常退出\n");
                }
                break;
            }
            else if(ret < 0)
            {
                printf("wait false\n");
                break; 
            }
            else 
            {
                // 等待期间让父进程干自己的事
                ExecuteTask();
                sleep(1);
            }
        }
    
    
    
    }


    return 0;
}


//int main()
//{
//    pid_t id = fork();
//    if(id < 0)
//    {
//        perror("fork");
//    }
//    else if(id == 0)
//    {
//        int cnt = 5;
//        while(cnt--)
//        {
//            
//            printf("i am child pid: %d, ppid: %d\n", getpid(), getppid());
//            sleep(1);
//        }
//    }
//    else 
//    {
//        int cnt = 10;
//        while(cnt--)
//        {
//            printf("i am parent pid: %d, ppid: %d\n", getpid(), getppid());
//            sleep(1);
//        }
//    }
//
//    return 0;
//}


// exit是库函数的进程退出，会执行清理等工作的函数
// _exit 是系统调用接口， 直接退出到操作系统
// 如下代码，exit退出，会清理缓存区，打印出you can see me!
// 但是_exit退出，不会清理缓存区，直接退出，不打印内容
//int main()
//{
//    printf("you can see me!");
//    sleep(1);
//
//    //exit(0);
//    _exit(11);
//}







// exit 和 _exit 可被随时调用，echo $?可以查看最近这一次进程的退出码

//void test()
//{
//    printf("hello Linux\n");
//    printf("hello Linux\n");
//    printf("hello Linux\n");
//    printf("hello Linux\n");
//    printf("hello Linux\n");
//    printf("hello Linux\n");
//    printf("hello Linux\n");
//    printf("hello Linux\n");
////    exit(11);
//    _exit(11);
//    printf("hello Linux\n");
//    printf("hello Linux\n");
//    printf("hello Linux\n");
//    printf("hello Linux\n");
//    printf("hello Linux\n");
//    printf("hello Linux\n");
//
//
//}
//
//
//int main()
//{
//    test();
//
//
//    return 0;
//}



// 进程退出码对应不同的信息
// 打印所有的进程退出码对应的字符信息
//int main()
//{
//    int i = 0;
//    for(;i < 200; i++)
//    {
//        printf("%d: %s\n", i, strerror(i));
//    }
//
//    return 0;
//}




//#define N 5
//
//void runChild()
//{
//    int cnt = 10;
//    while(cnt--)
//    {
//        printf("i am a process pid:%d, ppid: %d\n", getpid(), getppid());
//        sleep(1);
//    }
//}
//
//
//
//
//
//int main()
//{
//    int i = 0;
//    for(; i < N; i++)
//    {
//        pid_t id = fork();
//        if(id == 0)
//        {
//            runChild();
//            exit(0);
//        }
//    }
//





    //printf("i am a process\n");


//    return 0;
//}
